package com.fourfaith.iot.beidou.manager;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.HexUtil;
import com.fourfaith.common.utils.DateUtils;
import com.fourfaith.iot.beidou.decodec.BeiDouContants;
import com.fourfaith.iot.beidou.decodec.BeiDouEncoder;
import com.fourfaith.iot.beidou.handler.ChannelInitializerHandler;
import com.fourfaith.iot.beidou.message.Message;
import com.fourfaith.iot.beidou.message.inbound.BDfkiMessage;
import com.fourfaith.iot.beidou.message.outbound.CCtcqMessage;
import com.fourfaith.iot.beidou.pojo.bean.FkxxBean;
import com.fourfaith.iot.beidou.session.SessionFactory;
import com.fourfaith.iot.beidou.utils.MessageParseUtil;
import com.fourfaith.iot.device.cloud.access.dubbo.pojo.param.BeiDouParam;
import com.fourfaith.iot.device.cloud.access.dubbo.service.IBeidouDubboService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.*;

/**
 * @Name TcpManager
 * @Description ${}
 * @Author shiyunan
 * @Create 2022/3/4 11:54
 */
@Service
@Slf4j
public class TcpManager implements InitializingBean {

    /**
     * 是否启用netty
     */
    @Value("${netty.enable}")
    private int enable;

    /**
     * 端口
     */
    @Value("${netty.port}")
    private Integer port;

    @DubboReference(timeout = 10000)
    private IBeidouDubboService beidouDubboService;
    @Override
    public void afterPropertiesSet() throws Exception {
        init();
    }
    public void init() throws Exception {
        if (enable == 0) {
            return;
        }
        ThreadFactory beiDouThreadFactory = new ThreadFactoryBuilder().setNamePrefix("beiDou-pool").build();
        ExecutorService pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1), beiDouThreadFactory, new ThreadPoolExecutor.AbortPolicy());
        pool.execute(() -> {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializerHandler(beidouDubboService));
            try {
                //绑定端口，同步等待成功
                ChannelFuture f = bootstrap.bind(port).sync();
                log.info("run socket port=" + port);
                //等待服务监听端口关闭
                f.channel().closeFuture().sync();
            } catch (Exception e) {
                log.error("netty启动异常：{}", e.getMessage(), e);
            } finally {
                //退出，释放线程资源
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        });
    }

    public synchronized FkxxBean send(BeiDouParam beiDouParam) throws Exception {
        FkxxBean fkxxBean = new FkxxBean();
        MessageParseUtil.preSend();
        CCtcqMessage cCtcqMessage = new CCtcqMessage();
        cCtcqMessage.setAcceptorNumber(beiDouParam.getReceivedId());
        cCtcqMessage.setFrequencyPoint("2");
        cCtcqMessage.setInboundConfirm("1");
        cCtcqMessage.setEncodingType("3");
        cCtcqMessage.setData("A4" + beiDouParam.getMessageContext());
        cCtcqMessage.setFrequentness("0");
        byte[] data = BeiDouEncoder.encodeToByte(cCtcqMessage);
        Channel channel = SessionFactory.getSession().getChannel(BeiDouContants.BEI_DOU3);
        if (channel == null) {
            log.error("tcp,数据下发,服务未打开");
            fkxxBean.setSuccess(false);
            fkxxBean.setErrorMessage("tcp,数据下发,服务未打开");
            fkxxBean.setDelayTime(0);
            return fkxxBean;
        }
        log.info("tcp,数据下发,发送数据：{}", HexUtil.encodeHexStr(data));
        ChannelFuture channelFuture = channel.writeAndFlush(Unpooled.copiedBuffer(data));
        try {
            channelFuture.get();
            boolean await = MessageParseUtil.SEND_LOCK.await(10, TimeUnit.SECONDS);
            if(await){
                fkxxBean = MessageParseUtil.SEND_RESULT;
                return fkxxBean;
            }else {
                fkxxBean.setSuccess(false);
                fkxxBean.setErrorMessage("FKI发射未反馈状态");
                fkxxBean.setDelayTime(0);
                return fkxxBean;
            }
        } catch (Exception e) {
            fkxxBean.setSuccess(false);
            fkxxBean.setErrorMessage("tcp,数据下发,服务未打开");
            fkxxBean.setDelayTime(0);
            return fkxxBean;
        }
    }
}
